local ffi = require('ffi');

function bitswap(v,n,...)
    local args = {...};
    local r = 0;
    for i=0,n-1 do
        local pos = args[i+1];
        local vv = bit.band(bit.rshift(v,pos),1);
        r = bit.bor(r,bit.lshift(vv,n-i-1));
    end
    return r;
end

--[[
	ROM_REGION( 0x900000, "cslot1:maincpu", ROMREGION_BE|ROMREGION_16BIT )
	ROM_LOAD16_WORD_SWAP( "green.neo-sma",    0x0c0000, 0x040000, CRC(9cd55736) SHA1(d6efb2b313127c2911d47d9324626b3f1e7c6ccb) )  /* stored in the custom SMA chip, the SMA has a green colour marking */
	ROM_LOAD16_WORD_SWAP( "256-pg1.p1", 0x100000, 0x400000, CRC(b07edfd5) SHA1(dcbd9e500bfae98d754e55cdbbbbf9401013f8ee) ) /* TC5332202 */
	ROM_LOAD16_WORD_SWAP( "256-pg2.p2", 0x500000, 0x400000, CRC(6097c26b) SHA1(248ec29d21216f29dc6f5f3f0e1ad1601b3501b6) ) /* TC5332202 */
]]

function mslug3_en_68k(base,size)

    for i=0,ffi.sizeof(base)-1,2 do
        local tmp = base[i+0];
        base[i+0] = base[i+1];
        base[i+1] = tmp;
    end


    local buf = ffi.new('uint16_t[?]',size);
    --交换地址，使其逆向
        --0x400000/2
    local rom = ffi.cast('uint16_t*',( base + 0x100000));
    for i=0,0x400000-1,0x10000/2 do
        local buf = ffi.new('uint16_t[?]',0x10000/2);
        ffi.copy(buf,rom+i,0x10000)
        for j=0,0x10000/2-1 do
                                    --23,22,21,20,19,18,17,16,15,14,13,12,11,10,9, 8,7, 6,5,4 ,3,2, 1 ,0
                                    --23,22,21,20,19,18,17,16,15,2 ,11,0, 14,6, 4,13,8, 9,3,10,7,5, 12,1
            local set --bitswap(j,24, 23,22,21,20,19,18,17,16,15,11,8 ,1 ,13,4, 6, 7,3,10,2,9 ,5,14,0 ,12)
                    =   bitswap(j,24,23,22,21,20,19,18,17,16,15,2,11,0,14,6,4,13,8,9,3,10,7,5,12,1);
            rom[i+set] = buf[j];
        end
    end

    rom = ffi.cast('uint16_t*',base + 0x0);
    for i=0,0x0c0000/2 - 1 do
        rom[0x5d0000/2 + bitswap(i,24,23,22,21,20,19,18,15,2,1,13,3,0,9,6,16,4,11,5,7,12,17,14,10,8)] = rom[i];
    end

    rom = ffi.cast('uint16_t*',base + 0x100000);
    for i=0,0x800000/2-1 do
        --rom[i] = bitswap(rom[i],16,4,11,14,3,1,13,0,7,2,8,12,15,10,9,5,6);
        local v = rom[i];
                --    15,14,13,12,11,10, 9, 8,7, 6 ,5, 4 ,3 ,2, 1 ,0
                --     4,11,14, 3, 1,13, 0, 7,2, 8,12, 15,10,9, 5, 6
        v = bitswap(v,16,4,13,10, 5,14, 3, 2, 6,8, 0, 1, 15,12,7,11, 9);
        rom[i] = v;
    end



    --地址小于c0000/2 的
    --[[
    rom = base;
    for i=0,0xc0000/2 - 1 do
                                    --  23,22,21,20,19,18,17,16,15,14,13,12,11,10,9, 8,7, 6 ,5,4 ,3 ,2, 1 ,0
                                    --  23,22,21,20,19,18,15,2, 1 ,13,3 ,0 ,9 ,6 ,16,4,11,5 ,7,12,17,14,10,8
        rom[0x5d0000/2 + bitswap(i,24,  23,22,21,20,19,18, 5,11,17, 3,14, 5,8 ,1 ,11,0,5 ,10,6,8 ,13,16,15,12)] = rom[i];
    end
    ]]

    print(2);

    --[[
    for i=0,0x800000/2-1 do
        local v = rom[i];
                    --  15,14,13,12,11,10, 9, 8,7, 6 ,5, 4 ,3 ,2, 1 ,0
                    --   4,11,14, 3, 1,13, 0, 7,2, 8,12, 15,10,9, 5, 6
        v = bitswap(v,16,4,13,10, 5,14, 3, 2, 6,8, 0, 1, 15,12,7,11, 9);
        rom[i] = v;
    end
    ]]
    print(3);
end

function mslug3_decrypt_68k(base)
    local rom = ffi.cast('uint16_t*',base + 0x100000);
    for i=0,0x800000/2-1 do
        rom[i] = bitswap(rom[i],16,4,11,14,3,1,13,0,7,2,8,12,15,10,9,5,6);
    end
    rom = ffi.cast('uint16_t*',base + 0x0);
    for i=0,0x0c0000/2 - 1 do
        rom[i] = rom[0x5d0000/2 + bitswap(i,24,23,22,21,20,19,18,15,2,1,13,3,0,9,6,16,4,11,5,7,12,17,14,10,8)];
    end
    local rom = ffi.cast('uint16_t*',base + 0x100000);
    for i=0,0x800000/2-1,0x10000/2 do
        local buf = ffi.new('uint16_t[?]',0x10000/2);
        ffi.copy(buf,rom+i,0x10000);
        for j=0,0x10000/2-1 do
            rom[i+j] = buf[bitswap(j,24,23,22,21,20,19,18,17,16,15,2,11,0,14,6,4,13,8,9,3,10,7,5,12,1)];
        end
    end


    for i=0,ffi.sizeof(base)-1,2 do
        local tmp = base[i+0];
        base[i+0] = base[i+1];
        base[i+1] = tmp;
    end
end

assert(#arg>0,"no file");
local file = io.open(arg[1],"rb");
assert(file,"file open error")
local data = file:read("*a");
local rom = ffi.new('uint8_t[?]',#data);
ffi.copy(rom,data);
--print(rom[1]);
--print(ffi.sizeof(rom));

--mslug3_en_68k(rom,#data);
mslug3_decrypt_68k(rom,#data);
local out = arg[1]..'.d';
local file = io.open(out,"wb");
file:write(ffi.string(rom,#data));
file:close();

